package org.kernely.stream.administration;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.kernely.security.dao.PermissionDAO;
import org.kernely.security.dao.UserDAO;
import org.kernely.security.dao.UserDetailsDAO;
import org.kernely.security.persistence.Permission;
import org.kernely.security.persistence.User;
import org.kernely.security.persistence.UserDetails;
import org.kernely.stream.persistence.Stream;
import org.kernely.ui.mvp.KernelyPresenter;

import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;

public class StreamUserRightsPresenter extends KernelyPresenter<StreamUserRightsView>{

	/**
	 * The Stream to edit in edition mode
	 */
	private Stream stream;
	private boolean editMode = false;
	/**
	 * Available users for this stream
	 */
	private Set<User> selectableUsers;
	/**
	 * Already selected users for this stream
	 */
	private Map<User, Integer> selectedUsers;
	/**
	 * Users which rights have been removed
	 */
	private Set<User> removedUsers;

	public StreamUserRightsPresenter(){

	}

	public StreamUserRightsPresenter(Stream s){
		this.stream = s;
		this.editMode = true;
	}

	@Override
	public final void bind() {
		UserDAO udao = UserDAO.getInstance();
		selectedUsers = new HashMap<User, Integer>();
		selectableUsers = udao.getUsers();
		removedUsers = new HashSet<User>();
		
		// In edition mode, fill the fields with the informations
		if(stream != null && editMode){
			// Select all the permissions linked to the resource
			Set<Permission> perms = PermissionDAO.getInstance().findPermissionByResourceID(stream.getUid());
			if (perms == null){
				perms = new HashSet<Permission>();
			}			
			
			for(Permission p : perms){
				// Add users which have the permission to subscribe
				if(p.getRights().equals(StreamManagementWindowPresenter.SUBSCRIPTION_RIGHTS_STRING)){
					for(User u : p.getUsers()){
						fillSelectedUsers(u,StreamUserRightsView.SUBSCRIPTION_RIGHT);
						
						// We remove the user in selectableUsers list
						selectableUsers.remove(u);
					
					}
				}
				// Add users which have the permission to subscribe and write
				else if(p.getRights().equals(StreamManagementWindowPresenter.SUBSCRIPTION_REDACTION_RIGHTS_STRING)){
					for(User u : p.getUsers()){
						fillSelectedUsers(u,StreamUserRightsView.REDACTION_RIGHT);
						
						// We remove the user in selectableUsers list
						selectableUsers.remove(u);
					}
				}
				
				
				// Add users which have the permission to subscribe, write and delete messages
				else if(p.getRights().equals(StreamManagementWindowPresenter.SUBSCRIPTION_REDACTION_DELETEMESSAGES_RIGHTS_STRING)){
					for(User u : p.getUsers()){
						
						fillSelectedUsers(u,StreamUserRightsView.DELETE_RIGHT);
						
						// We remove the user in selectableUsers list
						selectableUsers.remove(u);
					}
				}

			}
		}

		lists();


		// Add a listener to the add button
		this.view.getAddButton().addListener(new Button.ClickListener() {
			/**
			 * The Serial Version ID
			 */
			private static final long serialVersionUID = -115612811698526312L;

			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				addUser();
			}
		});

		// Add a listener to the delete button
		this.view.getDeleteButton().addListener(new Button.ClickListener() {
			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				removeUser();
			}
		});
	}

	/**
	 * Adds a new user in the selected users list for this stream
	 */
	protected final void addUser() {
		UserDAO udao = new UserDAO();
		int userID = (Integer) this.view.getUsersBox().getValue();
		User user = udao.getUser(userID);

		selectableUsers.remove(user);
		selectedUsers.put(user, StreamUserRightsView.SUBSCRIPTION_RIGHT);
		removedUsers.remove(user);
		
		//Actualize lists
		lists();
	}

	/**
	 * Remove a user from the selected users list for this stream
	 */
	protected final void removeUser() {
		UserDAO udao = new UserDAO();
		Collection<Integer> removedUserID = (Collection<Integer>)this.view.getTable().getValue();
		for (Integer userID : removedUserID){
			User user = udao.getUser(userID);
			selectableUsers.add(user);
			selectedUsers.remove(user);
			removedUsers.add(user);
		}
		//Actualize lists
		lists();
	}

	/**
	 * Lists the selectable users in the combo box and the group users in the list.
	 */
	private final void lists(){
		UserDetailsDAO uddao = new UserDetailsDAO();

		// Remove all items
		this.view.getUsersBox().removeAllItems();
		this.view.getTable().removeAllItems();

		//List the group users
		for(Entry<User, Integer> e : selectedUsers.entrySet()){
			User u = e.getKey();
			if (u.getEnabled() == 1){
				UserDetails ud = uddao.getUserDetails(u);
				// Display user in the group's users list
				this.view.getTable().addItem(new Object[] {ud.getName(), e.getValue()}, u.getId());
			}
		}

		// List selectable users
		for(User u : selectableUsers){
			UserDetails ud = uddao.getUserDetails(u);
			// Only enabled users can be added to a group
			if (ud.getUser().getEnabled() == 1){
				this.view.getUsersBox().addItem(u.getId());
				this.view.getUsersBox().setItemCaption(u.getId(),
						ud.getFirstname()
						+ " "
						+ ud.getName()
						+ " (" + ud.getMail() + ")");
			}
		}
	}
	
	/**
	 * Add the user in the list of user who have rights on the stream.
	 * If the user was in the list with a right inferior or equal,
	 * the new right is set.
	 * @param u The user
	 * @param permission The permission (subscribe, write or delete messages)
	 */
	private final void fillSelectedUsers(User u, int permission){
		Integer actualValue = selectedUsers.get(u);
		if (actualValue == null || actualValue < permission){
			selectedUsers.put(u, permission);
		}
	}

	/**
	 * Gets the removedUsers, i.e. users that have no more rights on the stream
	 * @return the removedUsers
	 */
	public final Set<User> getRemovedUsers() {
		return removedUsers;
	}

	
	
}
